const path = require('path')
const knex = require('knex')
const jsyaml = require('js-yaml')
const fs = require('fs')

// 数据库配置文件路径
const dbConfigPath = path.join(__dirname, 'db.config.yaml')

// 加载数据库配置
let dbConfig
try {
  dbConfig = jsyaml.load(fs.readFileSync(dbConfigPath, 'utf8'))
  if (!dbConfig) {
    console.error('数据库配置文件为空')
    process.exit(1)
  }
} catch (error) {
  console.error('加载数据库配置文件失败:', error)
  process.exit(1)
}

// 添加连接池配置
const poolConfig = {
  min: 2, // 最小连接数
  max: 14, // 最大连接数
  acquireTimeoutMillis: 30000, // 获取连接超时时间
  createTimeoutMillis: 30000, // 创建连接超时时间
  idleTimeoutMillis: 30000, // 空闲连接超时时间
  reapIntervalMillis: 1000, // 清理间隔时间
  createRetryIntervalMillis: 200, // 重试间隔时间
  propagateCreateError: false, // 不传播创建错误
}

// 慢查询日志记录
const logSlowQueries = (query, ms) => {
  if (ms >= 1000) {
    // 记录执行时间超过1秒的查询
    console.warn(
      `[${new Date().toISOString()}] 慢查询 (${ms}ms): ${query.sql}`,
    )
    if (query.bindings && query.bindings.length) {
      console.warn(`参数: ${JSON.stringify(query.bindings)}`)
    }
  }
}

// 合并配置
const knexConfig = {
  ...dbConfig.db,
  pool: poolConfig,
  acquireConnectionTimeout: 60000, // 获取连接的超时时间
  debug: process.env.NODE_ENV === 'development', // 开发环境启用调试
  asyncStackTraces: process.env.NODE_ENV === 'development', // 开发环境启用异步堆栈跟踪
  log: {
    warn: (message) => console.warn(message),
    error: (message) => console.error(message),
    deprecate: (message) => console.warn(`弃用警告: ${message}`),
    debug: (message) =>
      process.env.NODE_ENV === 'development' && console.log(message),
  },
}

// 创建数据库连接实例
let db
try {
  db = knex(knexConfig)
  console.log('数据库连接池初始化成功')

  // 添加查询事件监听器，用于记录慢查询
  db.on('query', (query) => {
    query.startTime = Date.now()
  })

  db.on('query-response', (_response, query) => {
    const duration = Date.now() - query.startTime
    logSlowQueries(query, duration)
  })

  db.on('query-error', (error, query) => {
    const duration = Date.now() - query.startTime
    console.error(
      `[${new Date().toISOString()}] 查询错误 (${duration}ms): ${query.sql}`,
    )
    console.error(`错误: ${error.message}`)
    if (query.bindings && query.bindings.length) {
      console.error(`参数: ${JSON.stringify(query.bindings)}`)
    }
  })
} catch (error) {
  console.error('初始化数据库连接池失败:', error)
  process.exit(1)
}

// 添加连接池状态监控方法
const getPoolStatus = async () => {
  try {
    const pool = db.client.pool
    return {
      total: pool.numUsed() + pool.numFree(),
      active: pool.numUsed(),
      idle: pool.numFree(),
      pending: pool.numPendingAcquires(),
      timeouts: pool.numPendingCreates(),
    }
  } catch (error) {
    console.error('获取连接池状态失败:', error)
    return { error: '获取连接池状态失败' }
  }
}

// 添加连接测试方法
const testConnection = async () => {
  try {
    await db.raw('SELECT 1 as connection_test')
    return true
  } catch (error) {
    console.error('数据库连接测试失败:', error)
    return false
  }
}

// 定期检查连接池状态
setInterval(async () => {
  const status = await getPoolStatus()
  if (status.active > poolConfig.max * 0.8) {
    console.warn(
      `警告: 活跃连接数(${status.active})接近最大值(${poolConfig.max})`,
    )
  }
}, 30000)

// 进程退出时关闭连接池
process.on('SIGINT', async () => {
  console.log('正在关闭数据库连接池...')
  try {
    await db.destroy()
    console.log('数据库连接池已关闭')
    process.exit(0)
  } catch (error) {
    console.error('关闭数据库连接池时出错:', error)
    process.exit(1)
  }
})

module.exports = { db, knex, getPoolStatus, testConnection }
